﻿using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System.Text;

namespace LicenseDemo.Licenses;

/// <summary>
/// SM2 助手
/// </summary>
class Sm2Assistant
{
    #region 签名 & 验签
    /// <summary>
    /// 使用SM2私钥对数据进行签名
    /// </summary>
    /// <param name="data"></param>
    /// <param name="privateKey"></param>
    /// <returns></returns>
    public byte[] SignData(byte[] data, AsymmetricKeyParameter privateKey)
    {
        var signer = SignerUtilities.GetSigner("SM3WITHSM2");
        signer.Init(true, privateKey);
        signer.BlockUpdate(data, 0, data.Length);
        return signer.GenerateSignature();
    }

    /// <summary>
    /// 使用SM2公钥对数据进行验签
    /// </summary>
    /// <param name="data"></param>
    /// <param name="signature"></param>
    /// <param name="publicKey"></param>
    /// <returns></returns>
    public bool VerifyData(byte[] data, byte[] signature, AsymmetricKeyParameter publicKey)
    {
        var verifier = SignerUtilities.GetSigner("SM3WITHSM2");
        verifier.Init(false, publicKey);
        verifier.BlockUpdate(data, 0, data.Length);
        return verifier.VerifySignature(signature);
    }
    #endregion

    #region 加密 & 解密
    /// <summary>
    /// 公钥加密
    /// </summary>
    /// <param name="plainText"></param>
    /// <param name="publicKey"></param>
    /// <returns></returns>
    public string Encrypt(string plainText, AsymmetricKeyParameter publicKey)
    {
        SM2Engine engine = new();
        engine.Init(true, new ParametersWithRandom(publicKey, new SecureRandom()));
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
        byte[] encryptedBytes = engine.ProcessBlock(plainTextBytes, 0, plainTextBytes.Length);
        return Convert.ToBase64String(encryptedBytes);
    }

    /// <summary>
    /// 私钥解密
    /// </summary>
    /// <param name="encryptedText"></param>
    /// <param name="privateKey"></param>
    /// <returns></returns>
    public string Decrypt(string encryptedText, AsymmetricKeyParameter privateKey)
    {
        SM2Engine engine = new();
        engine.Init(false, privateKey);
        byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
        byte[] decryptedBytes = engine.ProcessBlock(encryptedBytes, 0, encryptedBytes.Length);
        return Encoding.UTF8.GetString(decryptedBytes);
    }
    #endregion

}
